package com.ifast.asset.controller;


import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.ifast.asset.domain.*;
import com.ifast.asset.service.*;
import com.ifast.asset.util.*;
import com.ifast.check.Controller.CheckTask;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.ifast.common.annotation.Log;
import com.ifast.common.base.BaseController;
import com.ifast.common.utils.Result;

/**
 * <pre>
 *
 * </pre>
 * <small> 2021-02-23 16:59:32 | Aron</small>
 */
@RestController
@RequestMapping("/wxmp/assets")
@Api(value = "资产接口")
public class AssetsController extends BaseController {
    @Autowired
    private AssetsService assetsService;
    @Autowired
    private TaskrecordService taskrecordServiceImpl;
    @Value("${checkUrl}")
    String checkUrl;
    @Autowired
    TaskipService taskipServiceImpl;
    @Autowired
    IpsegmentService ipsegmentServiceImpl;
    @Autowired
    LabelService labelService;
    @Autowired
    LabelassetService labelassetService;
    @Autowired
    AssetUtil assetUtil;
    @Autowired
    private SegmentService segmentService;

    @Value("${auditUrl}")
    String auditUrl;

    @GetMapping()
    @RequiresPermissions("wxmp:assets:assets")
    String Assets() {
        return "wxmp/assets/assets";
    }

    //@ResponseBody
    //@GetMapping("/list")
    //@RequiresPermissions("wxmp:assets:list")
    public Result<Page<Map<String, Object>>> list(Assets assetsDTO, Integer pageNum,
                                                  Integer pageSize, String labels) {
        //if (labels.isEmpty()){
        Wrapper<Assets> wrapper = new EntityWrapper<>();
        if (assetsDTO.getAssetsName() != null && !"".equals(assetsDTO.getAssetsName())) {

            wrapper.like("assetsName", assetsDTO.getAssetsName());
        }
        if (assetsDTO.getAssetsType() != null && !"".equals(assetsDTO.getAssetsType())) {

            wrapper.like("assetsType", assetsDTO.getAssetsType());
        }
        if (assetsDTO.getIp() != null && !"".equals(assetsDTO.getIp())) {

            wrapper.eq("ip", assetsDTO.getIp());
        }
        if (assetsDTO.getSource() != null && !"".equals(assetsDTO.getSource())) {

            wrapper.eq("source", assetsDTO.getSource());
        }
        wrapper.orderBy("time", false);
        Page<Assets> page = assetsService.selectPage(getPage(Assets.class, pageNum, pageSize), wrapper);
        //List<Assets> assets = assetsService.selectList(wrapper);
        //解析出本页的  资产信息   并去查询  对应标签信息
        List<Assets> lists = page.getRecords();

        List<Map<String, Object>> pageList = new ArrayList<>();
        for (int i = 0; i < lists.size(); i++) {
            //根据assetid 查询此资产的标签
            int assetid = lists.get(i).getId();
            Wrapper<LabelassetDO> labelassetDOWrapper = new EntityWrapper<>();
            labelassetDOWrapper.eq("assetId", assetid);
            List<LabelassetDO> labelassetDOS = labelassetService.selectList(labelassetDOWrapper);
            List<LabelDO> lables = new ArrayList<>();
            for (int j = 0; j < labelassetDOS.size(); j++) {

                //解析标签名称
                LabelDO labelDO = labelService.selectById(labelassetDOS.get(j).getLabelId());
                //if (labels.length > 0 && ListUtil.isContains(labels, labelDO.getId())) {
                //判断标签集合中是否存在当前标签
                if (!lables.contains(labelDO)) {
                    lables.add(labelDO);
                }
            }
            Map<String, Object> map = new HashMap<>();
            if (!labels.isEmpty()) {
                for (LabelDO lable : lables) {
                    //标签名包含搜索条件时执行
                    if (lable.getName().contains(labels)) {
                        map.put("lables", lables);
                    }
                }
            } else {
                map.put("lables", lables);
            }
            //标签不为空的情况下加入pageList
            if (map.get("lables") != null) {
                //map.put("lables", lables);
                Assets assets = lists.get(i);
                Wrapper taskipWrapper = new EntityWrapper();
                taskipWrapper.eq("ip", assets.getIp());
                taskipWrapper.orderBy("id", false);
                Map<String, Object> map2 = new HashMap<>();
                map2.put("id", assets.getId());
                map2.put("label", assets.getLabel());
                map2.put("ip", assets.getIp());
                map2.put("assetsName", assets.getAssetsName());
                map2.put("model", assets.getModel());
                map2.put("risk", assets.getRisk());
                map2.put("department", assets.getDepartment());
                map2.put("provide", assets.getProvide());
                map2.put("maintain", assets.getMaintain());
                map2.put("level", assets.getLevel());
                map2.put("time", assets.getTime());
                map2.put("source", assets.getSource());
                map2.put("score", assets.getScore());

                TaskipDO taskipDO = taskipServiceImpl.selectOne(taskipWrapper);
                if (taskipDO == null) {
                    map2.put("vendor", "");
                    map2.put("os", "");
                    map2.put("assetsType", "");
                    map2.put("mac", "");
                } else {
                    map2.put("vendor", taskipDO.getVendor());
                    map2.put("os", taskipDO.getOs());
                    map2.put("assetsType", taskipDO.getDevicetype());
                    map2.put("mac", taskipDO.getMac());
                }
                map.put("Assets", map2);
                pageList.add(map);
            }
        }
        List finalList = new ArrayList();
        int total = 0;
        if (!labels.isEmpty()) {
            finalList = getListByPage(pageList, pageNum, pageSize);
            total = pageList.size();
        } else {
            finalList = pageList;
            total = page.getTotal();
        }
        Page<Map<String, Object>> assetMap = new Page<>();
        assetMap.setRecords(finalList);
        assetMap.setCurrent(pageNum);
        assetMap.setTotal(total);
        assetMap.setSize(pageSize);
        return Result.ok(assetMap);
       /* }else {
            return Result.ok();
        }*/
    }


    //重写list接口
    @ResponseBody
    @PostMapping("/list")
    //@RequiresPermissions("wxmp:assets:list")
    Result<Object> listNew(@RequestBody AssetsDo assetsDTO) {

        Page page = new Page(assetsDTO.getPageNum(), assetsDTO.getPageSize());
        Map<String, Object> map = new HashMap<>();
        map.put("assetsName", assetsDTO.getAssetsName());
        map.put("assetsType", assetsDTO.getAssetsType());
        map.put("ip", assetsDTO.getIp());
        if (assetsDTO.getLabels()!=null&&!"".equals(assetsDTO.getLabels())){
            Wrapper wrapper = new EntityWrapper();
            wrapper.eq("name",assetsDTO.getLabels());
            LabelDO labelDO = labelService.selectOne(wrapper);
            if(labelDO!=null){

                map.put("lables", labelDO.getId());
            }

        }
        map.put("groupid", assetsDTO.getGroupId());
        List<Assets> assets = assetsService.selectPageNew(page, map);
        List<Object> lists = new ArrayList<>();
        //循环获取标签信息
        for (int i = 0; i < assets.size(); i++) {
            //根据assetid 查询此资产的标签
            int assetid = assets.get(i).getId();
            Wrapper<LabelassetDO> labelassetDOWrapper = new EntityWrapper<>();
            labelassetDOWrapper.eq("assetId", assetid);
            List<LabelassetDO> labelassetDOS = labelassetService.selectList(labelassetDOWrapper);
            List<LabelDO> lables = new ArrayList<>();
            Map<String, Object> resultmap = new HashMap<>();
            for (int j = 0; j < labelassetDOS.size(); j++) {

                LabelDO labelDO = labelService.selectById(labelassetDOS.get(j).getLabelId());
                lables.add(labelDO);
            }
            //丰富数据
            Wrapper wrapper = new EntityWrapper();
            wrapper.eq("ip", assets.get(i).getIp());
            wrapper.orderBy("id", false);
            TaskipDO taskipDO = taskipServiceImpl.selectOne(wrapper);
            resultmap.put("Assets", assets.get(i));
            resultmap.put("lables", lables);
            resultmap.put("taskip", taskipDO);
            lists.add(resultmap);
        }

        page.setRecords(lists);
        return Result.ok(page);
    }


    @GetMapping("/add")
        //@RequiresPermissions("wxmp:assets:add")
    String add() {
        return "wxmp/assets/add";
    }

    @GetMapping("/edit/{assetsId}")
    @RequiresPermissions("wxmp:assets:edit")
    String edit(@PathVariable("assetsId") Integer assetsId, Model model) {
        Assets assets = assetsService.selectById(assetsId);
        model.addAttribute("assets", assets);
        return "wxmp/assets/edit";
    }

    @Log("添加")
    @ResponseBody
    @PostMapping("/save")
    //@RequiresPermissions("wxmp:assets:add")
    public Result<String> save(@RequestBody AssetsLabel assetsLabel) {
        Assets assets = assetsLabel.getAssets();
        int[] lables = assetsLabel.getLabels();
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("ip", assets.getIp());
        List<Assets> lists = assetsService.selectList(wrapper);
        if (lists.size() > 0) {
            //更新资产库
            assetsService.updateById(assets);
            //更新标签库
            Wrapper labelassetWrapper = new EntityWrapper();
            labelassetWrapper.eq("assetId", assets.getId());
            labelassetService.delete(labelassetWrapper);
            for (int i = 0; i < lables.length; i++) {

                LabelassetDO labelassetDO = new LabelassetDO();
                labelassetDO.setAssetId(assets.getId());
                labelassetDO.setLabelId(lables[i]);
                labelassetService.insert(labelassetDO);
            }
            return Result.ok("已存在此ip的资产，执行更新操作");
        } else {
            //判断当前添加资产是否属于已添加网段
            List<IpsegmentDO> list = ipsegmentServiceImpl.selectList(null);
            if (list.size() == 0) {
                IpsegmentDO ipsegmentDO = new IpsegmentDO();
                String[] ip = (assets.getIp()).split("\\.");
                ipsegmentDO.setIp(ip[0] + "." + ip[1] + "." + ip[2] + ".0/24");
                ipsegmentServiceImpl.insert(ipsegmentDO);
            }
            for (int i = 0; i < list.size(); i++) {

                boolean isContain = IpUtil.getIsCrossIp(list.get(i).getIp(), assets.getIp());
                if (isContain) {
                    //包含
                    break;
                } else {
                    if (i == list.size() - 1) {
                        //不包含 则添加
                        IpsegmentDO ipsegmentDO = new IpsegmentDO();
                        String[] ip = (assets.getIp()).split("\\.");
                        ipsegmentDO.setIp(ip[0] + "." + ip[1] + "." + ip[2] + ".0/24");
                        ipsegmentServiceImpl.insert(ipsegmentDO);
                    }
                }
            }
            assetsService.insert(assets);
            //将数据添加
            for (int i = 0; i < lables.length; i++) {

                LabelassetDO labelassetDO = new LabelassetDO();
                labelassetDO.setAssetId(assets.getId());
                labelassetDO.setLabelId(lables[i]);
                labelassetService.insert(labelassetDO);
            }
            return Result.ok();
        }
    }

    @Log("修改")
    @ResponseBody
    @RequestMapping("/update")
    //@RequiresPermissions("wxmp:assets:edit")
    public Result<String> update(@RequestBody AssetsLabel assetsLabel) {
        Assets assets = assetsLabel.getAssets();
        int [] lables = assetsLabel.getLabels();
        assetsService.updateById(assets);

        //删除原有的标签
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("assetId",assets.getId());
        labelassetService.delete(wrapper);
        for (int i = 0 ; i < lables.length ; i++){
           LabelassetDO labelassetDO = new LabelassetDO();
            labelassetDO.setLabelId(lables[i]);
            labelassetDO.setAssetId(assets.getId());
            labelassetService.insert(labelassetDO);
        }

        return Result.ok();
    }

    @Log("删除")
    @PostMapping("/remove")
    @ResponseBody
    //@RequiresPermissions("wxmp:assets:remove")
    public Result<String> remove(Integer assetsId) {
        try {
            Assets assets = assetsService.selectById(assetsId);
            String[] ipArray = {assets.getIp()};
            deleteAllByIp(ipArray);
        } catch (Exception e) {

        }
        assetsService.deleteById(assetsId);
        return Result.ok();
    }

    @Log("批量删除")
    @PostMapping("/batchRemove")
    @ResponseBody
    //@RequiresPermissions("wxmp:assets:batchRemove")
    public Result<String> remove(@RequestBody Integer[] assetsIds) {
        try {
            List<String> ips = new ArrayList<>();
            for (int i = 0; i < assetsIds.length; i++) {

                Assets assets = assetsService.selectById(assetsIds[i]);
                ips.add(assets.getIp());

            }

            String[] ipArray = ips.toArray(new String[ips.size()]);
            deleteAllByIp(ipArray);
        } catch (Exception e) {

        }
        assetsService.deleteBatchIds(Arrays.asList(assetsIds));
        return Result.ok();
    }

    @ApiOperation("获取资产详情接口")
    @Log("资产详情接口")
    @PostMapping("/getAssetById")
    @ResponseBody
    public Result<Map<String, Object>> getAssetById(@RequestBody int id) {

        Assets assets = assetsService.selectById(id);
        Wrapper wrapper = new EntityWrapper();
        wrapper.orderBy("time", false);
        wrapper.eq("ip", assets.getIp());
        TaskipDO taskipDO = taskipServiceImpl.selectOne(wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("assets", assets);
        map.put("taskipDO", taskipDO);
        return Result.ok(map);
    }

    @ApiOperation("获取检测信息列表")
    @Log("获取检测信息接口")
    @PostMapping("/checkAsset")
    @ResponseBody
    public Result<String> checkAsset() {

        String url = checkUrl + "/newNmap-exe?code=" + "192.168.2.113" + "&summary=" + "测试11111";
        try {
            CloseableHttpClient client = null;
            CloseableHttpResponse response = null;
            try {
                HttpGet httpGet = new HttpGet(url);

                client = HttpClients.createDefault();
                response = client.execute(httpGet);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity);
                System.out.println(result);
            } finally {
                if (response != null) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.ok();
    }


    //根据多个ip获取资产详情
    @GetMapping("/getAssetsByPage")
    @ResponseBody
    public Result<List<Assets>> getAssetsByPage(String[] ips) {

        List<Assets> assets = new ArrayList<>();
        for (int i = 0; i < ips.length; i++) {

            Wrapper wrapper = new EntityWrapper();
            wrapper.eq("ip", ips[i]);
            Assets asset = assetsService.selectOne(wrapper);
            assets.add(asset);
        }
        return Result.ok(assets);
    }

    //查询开放端口最多的资产top10
    @GetMapping("/getMax10PortNum")
    @ResponseBody
    public Result<Object> getMax10PortNum() {

        LinkedList<TaskipDO>linkedList = new LinkedList();
        List<Assets> assets = assetsService.selectList(null);
        //根据  资产清单去寻找  检测记录
        for (int i = 0 ; i < assets.size() ; i ++){

            Wrapper wrapper = new EntityWrapper();
            wrapper.eq("ip",assets.get(i).getIp());
            wrapper.orderBy("time",false);
            TaskipDO taskipDO = taskipServiceImpl.selectOne(wrapper);
            //向链表中添加并且保持降序
            if (taskipDO!=null){

                if (linkedList.size()==0){
                    TaskipDO t = new TaskipDO();
                    t.setPortnum(0);
                    linkedList.add(0,t);
                }
                //顺序判断 链表中taskip 的portnum 大小
                for (int j = 0 ; j < linkedList.size() ; j++){

                    if(taskipDO.getPortnum()!=null&&taskipDO.getPortnum()>linkedList.get(j).getPortnum()){

                        linkedList.add(j,taskipDO);
                        if (linkedList.size()==11){
                            linkedList.remove(10);
                        }
                        break;
                    }else {
                        continue;
                    }
                }
            }
        }

        return Result.ok(linkedList);
    }


    //最近十天每天新增资产数
    @GetMapping("/getAddByDay")
    @ResponseBody
    public Result<Object> getAddByDay() {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map<String, Object>> maps = new ArrayList<>();
        for (int i = 0; i < 10; i++) {

            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -i);
            /*calendar.set(Calendar.HOUR_OF_DAY,0);·
            calendar.set(Calendar.MINUTE,0);
            calendar.set(Calendar.SECOND,0);
            calendar.set(Calendar.MILLISECOND,0);*/

            String dayStart = simpleDateFormat.format(calendar.getTime())+" 00:00:00";
            /*calendar.set(Calendar.HOUR_OF_DAY,23);
            calendar.set(Calendar.MINUTE,59);
            calendar.set(Calendar.SECOND,59);
            calendar.set(Calendar.MILLISECOND,999);*/
            String dayEnd = simpleDateFormat.format(calendar.getTime())+" 23:59:59";

            Wrapper wrapper = new EntityWrapper();
            wrapper.between("time",dayStart,dayEnd);
            //wrapper.setSqlSelect("UNIX_TIMESTAMP(time) >= UNIX_TIMESTAMP('" + dayStart + "')");
            //wrapper.setSqlSelect("UNIX_TIMESTAMP(time) <= UNIX_TIMESTAMP('" + dayEnd  + "')");
            List<Assets> lists = assetsService.selectList(wrapper);
            Map<String, Object> map = new HashMap<>();
            map.put("num", lists.size());
            map.put("time", simpleDateFormat.format(calendar.getTime()));
            maps.add(map);
        }
        return Result.ok(maps);
    }

    //当天离线在线数量
    @GetMapping("/getAssetStatus")
    @ResponseBody
    public Result<Object> getAssetStatus() {

        Map<String, Object> maps = new HashMap<>();
        Wrapper wrapperON = new EntityWrapper();
        wrapperON.eq("status",1);
        int on = segmentService.selectCount(wrapperON);
        Wrapper wrapperOFF = new EntityWrapper();
        wrapperOFF.eq("status",0);
        int off = segmentService.selectCount(wrapperOFF);
        maps.put("on",on);
        maps.put("off",off);
        return Result.ok(maps);
    }


    public List getListByPage(List list, int page, int pageSize) {
        if (list.size() > 0) {
            int firstIndex = (page - 1) * pageSize;
            int lastIndex = page * pageSize;
            int actualLastIndex = 0;
            if (list.size() >= lastIndex) {
                actualLastIndex = lastIndex;
            } else {
                actualLastIndex = list.size();
            }
            return list.subList(firstIndex, actualLastIndex);
        }
        return list;
    }

    public void deleteAllByIp(String[] ip) throws Exception {

        String url = auditUrl + "/deleteAllByIp";
        String res = HttpUtil.jsonDeleteRequest(url, JSON.toJSONString(ip), CheckTask.token);
    }
}
